//using System;
//using System.Collections.Generic;
//using System.Text;
//using VirtualRink.Library;
//using VirtualRink.Library.Simulation;

//namespace VirtualRink.Library.Simulation
//{
//    public class UrsaGameSimulator : IGameSimulator
//    {
//        TimeSpan duration;
//        Game game;
//        int homeTeamOffDefAverage = int.MinValue;
//        int visitingTeamOffDefAverage = int.MinValue;

//        int HomeTeamOffDefAverage
//        {
//            get
//            {
//                if(this.homeTeamOffDefAverage == int.MinValue)
//                {
//                    this.homeTeamOffDefAverage = this.GetTeamOffDefAverage(this.HomeTeam);
//                }
//                return this.homeTeamOffDefAverage;
//            }
//        }

//        int VisitingTeamOffDefAverage
//        {
//            get
//            {
//                if(this.visitingTeamOffDefAverage == int.MinValue)
//                {
//                    this.visitingTeamOffDefAverage = this.GetTeamOffDefAverage(this.VisitingTeam);
//                }
//                return this.visitingTeamOffDefAverage;
//            }
//        }

//        private Team HomeTeam
//        {
//            get { return game.HomeTeam; }
//        }

//        private Team VisitingTeam
//        {
//            get { return game.VisitingTeam; }
//        }
        
//        public void Simulate(Game game)
//        {
//            DateTime start = DateTime.Now;

//            this.game = game;

//            Validate();

//            this.SimulateScoring();
//            this.SimulatePenalties();



//            DateTime end = DateTime.Now;
//            this.duration = end.Subtract(start);
//        }

//        public TimeSpan Duration
//        {
//            get { return duration; }
//        }

//        void Validate()
//        {
//            if(this.game.Played)
//            {
//                throw new SimulationException("This game has already been played.");
//            }

//            if(this.HomeTeam.RosterIsValid().IsValid == false)
//            {
//                throw new SimulationException("Home team roster is not valid.");
//            }
//            if(this.VisitingTeam.RosterIsValid().IsValid == false)
//            {
//                throw new SimulationException("Visiting team roster is not valid.");
//            }
//        }

//        void SimulateScoring()
//        {
//            //get total number of shots
//            int shots = Randomizer.NextNormal(50, 10);

//            //initialize array of game seconds
//            int[] shotGameSeconds = new int[shots];

//            for(int i = 0;i < shotGameSeconds.Length;i++)
//            {
//                shotGameSeconds[i] = Randomizer.Next(3, 3600);
//                this.SimulateShot(shotGameSeconds[i]);
//            }

//            //determine if the game is a tie
//            bool tie = this.GameIsTie();

//            //settle the tie
//            if(tie)
//            {
//                this.SettleTie();

//            }
//        }

//        void SettleTie()
//        {
//            bool isTie = true;
//            int nextSecondStart = 3600 + 3;
//            int nextSecondMax = 20;
//            int nextSecond;
//            int max = int.MaxValue - 1;
//            int count = 0;

//            //play to the death.  no overtime limit.
//            while(isTie)
//            {
//                nextSecond = Randomizer.Next(nextSecondStart, nextSecondStart + nextSecondMax);
//                this.SimulateShot(nextSecond);
//                nextSecondStart = nextSecond + 10;
//                isTie = this.GameIsTie();

//                count = count + 1;
//                if(count >= max)
//                {
//                    throw new SimulationException("Tie-breaking period never ended.");
//                }
//            }
//        }

//        private bool GameIsTie()
//        {
//            int homeCount = 0;
//            int visitorCount = 0;
//            foreach(Goal goal in game.Goals)
//            {
//                if(goal.Shooter.CurrentTeam == game.HomeTeam)
//                {
//                    homeCount = homeCount + 1;
//                }
//                else
//                {
//                    visitorCount = visitorCount + 1;
//                }
//            }

//            if(homeCount.Equals(visitorCount))
//            {
//                return true;
//            }
//            return false;

//        }

//        private void SimulateShot(int gameSecond)
//        {
//            //determine who is the shooter
//            Player shooter = this.DetermineShooter();
//            Shot shot = Shot.Create();
//            shot.Player = shooter;
//            shot.Game = this.game;
//            game.Shots.Add(shot);

//            //determine if it's a goal
//            Player goalie;
//            if(shooter.CurrentTeam == game.HomeTeam)
//            {
//                goalie = game.VisitingTeam.GetGoalie();
//            }
//            else
//            {
//                goalie = game.HomeTeam.GetGoalie();
//            }

//            bool shotIsGoal = this.DetermineShotIsGoal(shooter, goalie);

//            if(shotIsGoal)
//            {
//                Goal goal = Goal.Create();
//                goal.Shooter = shooter;

//                IList<Player> assists = this.GetAssists(goal.Shooter);
//                if(assists.Count >= 1)
//                {
//                    goal.Assist1 = assists[0];
//                }
//                if(assists.Count >= 2)
//                {
//                    goal.Assist2 = assists[1];
//                }

//                goal.Period = this.DeterminePeriod(gameSecond);
//                int secondsInPeriod = 60 * 20;
//                int diff = gameSecond - (secondsInPeriod * (goal.Period - 1));
//                goal.Second = diff;
//                game.Goals.Add(goal);
//            }
//        }

//        private IList<Player> GetAssists(Player shooter)
//        {
//            List<Player> players = new List<Player>();

//            Dictionary<Player, double> playerFactors = new Dictionary<Player, double>();
//            double offenseWeight = 2;
//            double speedWeight = 1;
//            double passingWeight = 3;
//            double averageCount = 3;
//            Team shootingTeam = shooter.CurrentTeam;

//            foreach(Player player in shootingTeam.CurrentPlayers)
//            {
//                double factor = player.OffensiveAwareness * offenseWeight +
//                    player.Speed * speedWeight +
//                    player.Passing * passingWeight;
//                double average = factor / averageCount;
//                double finalFactor = average * Convert.ToDouble(Randomizer.Next(1, 100));
//                playerFactors.Add(player, finalFactor);
//            }

//            Player assistor1 = null;
//            double highest = 0;
//            foreach(Player key in playerFactors.Keys)
//            {
//                if(playerFactors[key] > highest)
//                {
//                    highest = playerFactors[key];
//                    assistor1 = key;
//                }
//            }

//            Player assistor2 = null;
//            int random = Randomizer.Next(1, 100);
//            if(random > 50)
//            {
//                //create a 2nd assist
//                highest = 0;
//                foreach(Player key in playerFactors.Keys)
//                {
//                    if(key != assistor1)
//                    {
//                        if(playerFactors[key] > highest)
//                        {
//                            highest = playerFactors[key];
//                            assistor2 = key;
//                        }
//                    }
//                }
//            }

//            players.Add(assistor1);
//            if(assistor2 != null)
//            {
//                players.Add(assistor2);
//            }
            
//            return players;
//        }

//        private Player CreateAssistor(Team team, Player shooter)
//        {
//            int index = Randomizer.Next(0, team.CurrentPlayers.Count - 1);
//            Player player = team.CurrentPlayers[index];
//            if(player.Id != shooter.Id)
//            {
//                return player;
//            }
//            return null;
//        }

//        private int DeterminePeriod(int gameSecond)
//        {
//            int secondsInPeriod = 60 * 20;
//            if(gameSecond <= secondsInPeriod)
//            {
//                return 1;
//            }
//            else if(gameSecond <= secondsInPeriod * 2)
//            {
//                return 2;
//            }
//            else if(gameSecond <= secondsInPeriod * 3)
//            {
//                return 3;
//            }
//            else
//            {
//                return 4;
//            }
//        }

//        private Player DetermineShooter()
//        {
//            Team shootingTeam = this.DetermineShootingTeam();
//            Dictionary<Player, double> playerFactors = new Dictionary<Player, double>();
//            double offenseWeight = 2;
//            double speedWeight = 1.5;
//            double shootingWeight = 3;
//            double passingWeight = -1.5;
//            double averageCount = 4;

//            foreach (Player player in shootingTeam.CurrentPlayers)
//            {
//                double factor = player.OffensiveAwareness * offenseWeight +
//                    player.Speed * speedWeight +
//                    player.Shooting * shootingWeight +
//                    player.Passing * passingWeight;
//                if(string.Compare(player.Position, Constants.DefenseAbbreviation, true) == 0)
//                {
//                    //defensemen don't shoot as often.
//                    factor = factor * .9;                    
//                }
//                double average = factor / averageCount;
//                double finalFactor = average * Convert.ToDouble(Randomizer.Next(1, 100));
//                playerFactors.Add(player, finalFactor);
//            }

//            Player shooter = null;
//            double highest = 0;
//            foreach(Player key in playerFactors.Keys)
//            {
//                if(playerFactors[key] > highest)
//                {
//                    highest = playerFactors[key];
//                    shooter = key;
//                }
//            }
//            return shooter;
//        }

//        private int GetTeamOffDefAverage(Team team)
//        {
//            int total = 0;
//            int count = 0;
//            foreach(Player player in team.CurrentPlayers)
//            {
//                if(!player.IsGoalie)
//                {
//                    total = total + player.DefensiveAwareness + player.OffensiveAwareness;
//                    count = count + 1;
//                }
//            }
//            int average = total / (count * 2);
//            return average;
//        }

//        private Team DetermineShootingTeam()
//        {
//            int homeRandom = Randomizer.Next(1, 100);
//            int visitorRandom = Randomizer.Next(1, 100);

//            int homeValue = homeRandom * this.HomeTeamOffDefAverage;
//            int visitorValue = visitorRandom * this.VisitingTeamOffDefAverage;

//            if(homeValue > visitorValue)
//            {
//                return this.HomeTeam;
//            }
//            else
//            {
//                return this.VisitingTeam;
//            }
//        }

//        private bool DetermineShotIsGoal(Player shooter, Player goalie)
//        {
//            double offenseWeight = 1;
//            double shootingWeight = 1;
//            double speedWeight = 1;
//            double averageDenom = 3;
//            double shooterFactor = shooter.OffensiveAwareness * offenseWeight +
//                shooter.Shooting * shootingWeight +
//                shooter.Speed + speedWeight;
//            double shooterAverage = shooterFactor / averageDenom;

//            double goalieAverage = goalie.Goaltending;

//            double shooterPenalty = .5; //need to temper the shooters
//            double shooterValue = shooterAverage * Randomizer.Next(1, 100) * shooterPenalty;
//            double goalieValue = goalieAverage * Randomizer.Next(1, 100);

//            return shooterValue > goalieValue;

//        }

//        void SimulatePenalties()
//        {
//            int penalties = 0;


//            //get total number of penalties
//            penalties = Randomizer.NextNormal(6, 3);

//            if(penalties < 1)
//            {
//                return;
//            }

//            //initialize array of game seconds
//            int[] penaltyGameSeconds = new int[penalties];


//            for(int i = 0;i < penaltyGameSeconds.Length;i++)
//            {
//                penaltyGameSeconds[i] = Randomizer.Next(3, 3600);
//                this.SimulatePenalty(penaltyGameSeconds[i]);
//            }

//        }

//        private void SimulatePenalty(int gameSecond)
//        {
//            //determine who is the offender
//            Player offender = this.DetermineOffender();

//            string penaltyType = this.DeterminePenaltyType();
//            int secondsInPeriod = 60 * 20;

//            Penalty penalty = Penalty.Create();
//            penalty.Player = offender;
//            penalty.PenaltyType = penaltyType;
//            penalty.Game = this.game;
//            penalty.Period = this.DeterminePeriod(gameSecond);
//            int diff = gameSecond - (secondsInPeriod * (penalty.Period - 1));
//            penalty.Second = diff;
//            penalty.Duration = 2;

//            this.game.Penalties.Add(penalty);

//            if(penaltyType == Penalties.PenaltyFighting)
//            {
//                Player offender2 = this.DetermineOffender(offender);
//                Penalty penalty2 = Penalty.Create();
//                penalty2.Player = offender2;
//                penalty2.PenaltyType = penaltyType;
//                penalty2.Game = this.game;
//                penalty2.Period = penalty.Period;
//                penalty2.Second = penalty.Second;
//                penalty2.Duration = penalty.Duration;
//                this.game.Penalties.Add(penalty2);
//            }

//        }

//        private string DeterminePenaltyType()
//        {
//            int random = Randomizer.Next(1, 100);
//            if(random < 25)
//            {
//                return Penalties.PenaltyHolding;
//            }
//            if(random < 45)
//            {
//                return Penalties.PenaltyHooking;
//            }
//            if(random < 67)
//            {
//                return Penalties.PenaltySlashing;
//            }
//            if(random < 90)
//            {
//                return Penalties.PenaltyTripping;
//            }
//            if(random <= 100)
//            {
//                return Penalties.PenaltyFighting;
//            }
//            return Penalties.PenaltyHolding;
//        }

//        private Player DetermineOffender()
//        {
//            List<Player> allPlayers = new List<Player>();
//            allPlayers.AddRange(this.HomeTeam.CurrentPlayers);
//            allPlayers.AddRange(this.VisitingTeam.CurrentPlayers);

//            Dictionary<Player, double> playerFactors = new Dictionary<Player, double>();

//            foreach(Player player in allPlayers)
//            {
//                double finalFactor = Convert.ToDouble(player.Checking) * Convert.ToDouble(Randomizer.Next(1, 100));
//                playerFactors.Add(player, finalFactor);
//            }

//            Player offender = null;
//            double highest = 0;
//            foreach(Player key in playerFactors.Keys)
//            {
//                if(playerFactors[key] > highest)
//                {
//                    highest = playerFactors[key];
//                    offender = key;
//                }
//            }


//            return offender;

//        }
        
//        private Player DetermineOffender(Player partner)
//        {
//            List<Player> allPlayers = new List<Player>();
//            allPlayers.AddRange(this.HomeTeam.CurrentPlayers);
//            allPlayers.AddRange(this.VisitingTeam.CurrentPlayers);

//            Dictionary<Player, double> playerFactors = new Dictionary<Player, double>();

//            foreach(Player player in allPlayers)
//            {
//                double finalFactor = Convert.ToDouble(player.Checking) * Convert.ToDouble(Randomizer.Next(1, 100));
//                playerFactors.Add(player, finalFactor);
//            }

//            Player offender = null;
//            double highest = 0;
//            foreach(Player key in playerFactors.Keys)
//            {
//                if(key.Id != partner.Id && playerFactors[key] > highest)
//                {
//                    highest = playerFactors[key];
//                    offender = key;
//                }
//            }
//            return offender;

//        }

//    }
//}
